大判例

20世紀の現憲法下の裁判例を掲載しています。

神戸地方裁判所 平成6年(ワ)712号 判決 1997年8月20日

神戸市中央区葺合町馬止1番10号 マジカルビル

原告

魔法株式会社

右代表者代表取締役

松浦博司

右訴訟代理人弁護士

工藤涼二

滝本雅彦

北山真

東京都台東区台東2丁目4番3号

被告

株式会社ログ

右代表者代表取締役

松本博司

右訴訟代理人弁護士

藤原宏高

右訴訟復代理人弁護士

小林弘卓

井奈波朋子

主文

一  原告の請求をいずれも棄却する。

二  訴訟費用は原告の負担とする。

事実及び理由

第一  請求

一  被告は原告に対し、金1060万円及びこれに対する平成6年5月13日から完済に至るまで年5分の割合による金員を支払え。

二  被告は、原告の別紙物件目録記載のパソコン用ゲームソフトウエアの販売を妨害してはならない。

第二  事案の概要

本件は、原告が、原告の開発にかかるパソコン用将棋ソフトウエアの販売は被告の著作権を侵害するものではないのに、被告はそのことを知りながら、原告を債務者として原告の右ソフトウエア販売禁止の仮処分を申請して原告の右販売を妨害し、原告の経済的信用を毀損する行為をしたとして、被告に対し、不法行為に基づく損害賠償及び著作権に基づく妨害行為の差止を請求した事案である。

争いのない事実

1  原告は、コンピュータ・ソフトウエアの開発、販売等を営業目的とする会社である。

2  被告は、原告と同様コンピュータ・ソフトウエアの開発、販売等を営業目的とする会社であり、別紙著作権目録記載の著作権(以下「被告著作権」といい、同目録二のプログラムを「被告ソフト」という。)を有している。

3  原告は、別紙物件目録記載のプログラム(以下「原告ソフト」という。)を開発し、その販売をビクターエンタテインメント株式会社(以下「ビクターエンタテインメント」という。)に委託し、同社は平成6年2月25日より原告ソフトの販売を開始した。

4  (被告の仮処分申請)

(一)  被告は、平成6年3月10日、ビクターエンタテインメントを債務者として、東京地方裁判所に原告ソフトの販売禁止の仮処分申請(同裁判所平成6年(ヨ)第22、020号事件・以下「本件仮処分申請」という。)をした。

(二)  被告の本件仮処分申請の理由は、原告ソフトは、被告ソフトのマシン語プログラムのうち、アセンブラレベルで最も重要な思考ルーチンの大部分を違法に複製したもので、ビクターエンタテインメントの原告ソフトの販売は被告著作権を侵害するというものであった。

二 争点

1  原告ソフトの販売は、被告著作権を侵害するものか(原告ソフトは、被告ソフトのプログラムの重要な部分と同一ないし類似のものか)。

2  被告の本件仮処分申請は不法行為を構成するか。

3  原告の損害額

三 原告の主張

1  原告ソフトは被告ソフトのマシン語プログラムち重要な部分を複製したものではなく、原告ソフトの販売は被告著作権を侵害するものではない。その理由は以下のとおりである。

(一)  著作物とは、思考又は感情を創作的に表現したものであって、文芸、学術、美術又は音楽の範囲に属するものをいう(著作権法2条1項1号)。

右の「創作性」に関しては、各著作物の特性に応じて考えていくべきである。

著作物については、いわゆるOTAリポートによれば、<1>芸術作品、<2>事実作品、<3>機能作品の3種類のカテゴリーに分類されているが、本件で問題となっているコンピュータ・プログラム(ソフトウエア)は、いうまでもなく<3>の機能作品に属するものである。<1>の芸術作品のカテゴリーにおいては、単なる「個性」の「表現」と認められるものであれば著作物と認められようが、機能性が重視されるコンピュータ・プログラムにおいては、他のカテゴリーの著作物とは全く異なる特徴があり、これらと同様に考えることはできないこと、つまり、機能作品であるコンピュータ・プログラムにおいては、創作性のレベルについて、保護するに足りるだけの水準を有していることが必要とされてきたのである(西ドイツ連邦通常裁判所1985年5月9日判決〔甲16〕、東京高等裁判所平成元年6月20日決定〔システムサイエンス事件〕参照)。

(二)  被告は、本件仮処分申請において、原告ソフトが被告ソフトの「MOVEP」なるユーザー定義関数を複製したものであるとして、それを理由に被告著作権の侵害を主張している。

しかし、被告ソフトの「MOVEP」に相当する原告ソフトのルーチン「com-itte」(以下「com-itte」という。)自体は、単に駒を進めて評価値を得るという動作をしているに過ぎず、どの将棋ゲームソフトにも、プログラム上の表現方法としては異なるものもあるが、機能としては必ず存在するもので、独創性のあるものではない。すなわち、この部分は、基本的には、コンピュータ内部で駒を-手進める手順を示しているだけで、思考、判断は殆どしておらず、その意味では中身はないといってよい。将棋ゲームソフトで重要な「強さ」「速さ」といった中身に関しては、すべて別のルーチンに移行してこれを使用しているためである。

この部分の動作は、具体的には次のようなものである。

(1) 計算前の初期化

(2) 指す駒の利きを消す。

(3) 指す駒により影響される飛び駒の利きを消す。

(4) 駒を指す処理

<1> 取った駒の処理

<2> 成った駒の処理

<3> 指した駒の処理

これらは、指した駒を盤上で移動させたり、単に駒の持ち主を入れ替えたりするものである。

(5) 駒を指すことにより新しく利きをセットする。

(6) 駒を指した盤面を評価する。

(7) 評価終了の印をつける。

この各段階のうち、他のサブルーチンを使用せずにこの関数で処理しているのは、前記の(1)と(4)のみである。その他は、単に処理の順番を示しているに過ぎない。

したがって、被告ソフトの「MOVEP」に創作性はないから、原告ソフトの「com-itte」部分に被告ソフトの「MOVEP」に類似する部分があることをもって、被告著作権の侵害であるとする被告の主張は失当である。

(三)  被告の本件仮処分申請の理由は、将棋ソフトの開発において似た解法(アルゴリズム)を採用した結果、指し手が類似することをもって複製というにすぎず、たとえアルゴリズムが同じであっても著作権の侵害とはいえないのであるから、被告の主張が失当であることは明らかである。また、複製によって開発されたプログラムでなくても、同じアルゴリズムのプログラム間ではアセンブラレベルで同一のコードを含むことはよく認められることで、このことから原告ソフトが被告ソフトの複製によると結論づけることも失当である。さらに、将棋ゲームソフトの開発においては、コンピューター側の強さ(棋力)とともに、コンピューターの思考時間の短さ(一手指すのに長時間必要であればゲームとしての商品価値は劣る)が重要であるが、被告の主張は思考時間の違い(ゲームレベルによっては、被告ソフトは原告ソフトの2倍以上の思考時間を要する。)を全く無視したものである。

(四)  被告は、「MOVEP」からコールされている関数の一部をあげて、殆ど同一のものであり、多少異なる部分も原告が単に最適化(オプティマイズ)しただけにすぎない、と主張する。

しかし、被告の主張では、オプティマイズされたプログラムもされていないプログラムも、同一の物であるということになるが、これは明らかに誤りである。ソフトウエアの開発において、特に一般向けコンピュータの場合、オプティマイズは重要な要素である。これは、一般向けコンピュータは性能が低く、処理速度も遅いため、ソフトウエアをより軽量化、高速化して対処しなければならない。したがって、オプティマイズされ、非常に反応のよい(処理速度の速い)ソフトウエアは、たとえ同じ結果をもたらすものであっても価値があり、それ自体が著作物といえるのである。

すなわち、原告において両ゲームソフトを使用して棋譜を指し、思考時間を計測したところ、16%の速度向上が見られたが、この速度向上率は単なるオプティマイズだけでは実現不可能である。被告ソフトの「MOVEP」は115ステップで構成されているのに対し、原告ソフトの「com-itte」は9ステップ少ない106ステップで構成されているが、もし、原告ソフトがこのようなオプティマイズのみによって複製されたものであるとすると、速度向上率は106/115となり、8%未満である。被告の主張するようなオプティマイズでは実測されるような速度差は発生しない。この速度差は、思考レベルを上げて(より深く思考させて)比較すると、さらに大きくなる。仮に、被告の主張するように原告ソフトがオプティマイズのみよっていたとしても、このような大きな処理速度向上がもたらされるようなプログラムは、それ自体に著作物性が認められる。

さらに、オプティマイズ自体では、処理速度に変化が生ずるが、処理結果は同一のはずである。しかし、原告ソフトと被告ソフトでは処理結果は異なるのである。被告が具体的に処理結果が同一となるものとして示したものは、数多い指し手数の中の極く僅かな部分にすぎない。これをもってみても、原告ソフトが被告ソフトの思考モジュールの関数をオプティマイズしたすぎず、違法にその大部分を複製したものであるなどといえるものではないことは明白である。

(五)  また、被告は、被告ソフトのマシン語プログラムのうち関数「listup long」(以下「「listup long」という。)の部分に相当する原告ソフトのプログラム部分が被告著作権を侵害する旨主張するが、右の各部分のサブルーチンは、単にいわゆる飛び駒をリストアップする処理をするだけのものにずぎないところ、利きに入った飛び駒をリストアップする処理は、将棋思考に必ず存在する処理であり、将棋ソフトの価値を決める強さや速さに直接関係のないものであるから、創作性のないものである(右のような単純な処理に創作性を認めるならば、オプティマイズしたものにも創作性を認めることになり、妥当ではない。)。

2  被告は、原告ソフトが被告ソフトのプログラムを複製したものではないこと(被告著作権を侵害していないこと)を認識しながら、本件仮処分申請をして原告の原告ソフト販売行為を妨害する等し、原告に対して後記のとおりの損害を与えたものであるから、被告の行為は不法行為を構成する。

3  原告は、被告の不法行為により次のとおりの合計1060万円の損害を被った。

(一)  逸失利益 60万円

(1) 原告は、被告の本件仮処分申請により、平成6年4月15日ビクターエンタテインメントとの販売委託契約を解除せざるを得なくなり、その結果原告ソフトの販売を阻害された。

(2) 原告ソフトの販売価格は1個1万2800円であり、そのうち2000円が純利益として見込まれ、また、原告ソフトが市販されていたならば、少なくとも毎月900個の販売は確保できた。

したがって、前記原告とビクターエンタテインメントとの販売委託契約解除の日から本訴提起の日の前日(平成6年4月24日)までの10日間の原告の逸失利益は60万円(2000円×900個×10日/30日=60万円)となる。

(二)  信用毀損の損害 1000万円

原告は、被告の本件仮処分申請において、被告からあたかも他社の商品を違法にコピーしたかのごとく言われたことにより、業界における経済的信用を非常に傷つけられる結果となった。この原告の被害を金銭で評価すれば、1000万円を下らない。

四 被告の主張

原告ソフトは、被告ソフトの重要な部分を複製したものであり、被告著作権を一部侵害するものである。その理由は以下のとおりである。

1  レジスタ(変数)について

インテル8086系マシン語には、以下のレジスタ(一語又は数語を一時的に保持する記憶回路)が存在する。かかるレジスタやメモリの演算によってコンピュータのソフトウエアが作動する。

(一)  AX、BX、CX、DX

汎用レジスタであり、様々な演算に使用する。

0-65535又は-32768、-32767の範囲を持っ。また、AH、ALの用にAXを2つに分けて使用することができる(AHはAXのハイバイト、ALはAXのローバイトを意味する)。

この場合の範囲は、0-255又は-128、-127の範囲を持つ。

また、BXはアドレスレジスタに、CXはカウンターレジスタに使用されることが多い。

(二)  SI、DI

インデックスレジスタであり、メモリをアクセスするインデックスに使用される。

範囲は、0-65535又は-32768、-32767の範囲を持つ。

また、汎用レジスタのようにH、Lには分けられない。

(三)  IP、BP、SP

ポインターレジスタであり、プログラムの実行中のアドレスや、スタックに関するレジスタである。

範囲は、0-6535、-32768、-32767の範囲を持つ。

(四)  CS、DS、ES、SS

セグメントレジスタである。今までのレジスタとは違い、レジスタの範囲が16ビットだと最高64KBのメモリ空間しかアクセスできないが、このセグメントレジスタと他のインデックス、ポインターレジスタのオフセットにより、64KB以上のメモリをアクセスできるようにするレジスタである。

(五)  スタック

レジスタを一時的に保存して後で元の数値に戻したり、他のサブルーチンにパラメータを送るときの受け渡し用に使用する。

また、サブルーチンに移行し、元のルーチンに戻る時に参照される。

そのため、このスタックは非常に大事な役目である。

2  被告ソフトの「MOVEP」について

(一)  被告ソフトの関数「MOVEP」は、現在のメモリ上の局面でパラメーターとして与えられた指し手を実行し、その局面を評価し点数化するルーチンである(ただし、評価自体は違う関数で行われている)。

(二)  被告ソフトの「MOVEP」と原告ソフトのこれに相当するルーチン(「com-itte」)とを対比すると、別表1プログラム対比表記載のとおりとなり(「聖天」が原告ソフト、「極」が被告)、その結果は次のとおりである。

(1) 命令及びデータが同じもの

1~6、8、10~11、14、16、19~20、22~25、28、30~35、38~42、44~45、47~48、50~53、60、64、66~70、73~81、84~87、89~90、92、96、98~99、101~102、111~115

(2) 表示上違いがあるが、内容は全く同じもの

これは、被告ソフトのソースリストが、「00」を「setenvp」と別名で定義しているため、「00」の部分が「setenvp」と記載されている場合であり、プログラムの内容は、全く同じである。

71、82

(3) メモリーアクセスのアドレスが変わっているもの

これは、メモリー上に変数が配置されているために、プログラムの読み込まれる位置によってアドレスに変化が生じているが、命令の意味は全く同じである。

7、9、15、17、18、61、65

(4) プログラムの分岐(JMP JZ JNZなど)やサプルーチンコールの先の違うもの

これは、プログラムの読み込まれる位置によってアドレスに変化が生じているが、命令の意味は全く同じである。

12、13、21、27、29、37、43、46、49、63、72、83、91、94、97、100、103、109、110

(5) メモリーに配置された変数の値の比較をしているが、比較する先の違うもの

これは、プログラムの読み込まれる位置によってアドレスに変化が生じているが、命令の意味は全く同じである。

26、54、62、93

(6) それ以外の違い

36 被告ソフトの36行は、セグメントレジスタESの内容をインデックスレジスタDIにコピーするものであるが、36行時点のESの値は30行でDIをコピーした物で、その後DIの値に変化はないので36行は不必要になる。

原告ソフトは、以上の理由から36行を削除したものである。

55~59

原告ソフトの55行は、被告ソフトの55行ないし59行を最適化したものであり、被告ソフトが55行ないし59行の命令で実行している内容を、原告ソフトは55行のみで実行しているものである。

88、95

被告ソフトのこの行は、6行で読み込まれたレジスタESの読み直しであり、その間のレジスタESは破壊されていないので不必要な命令である。そこで、原告ソフトはこれを削除したものである。

104~105、107~108

この部分は、被告ソフトの命令を、原告ソフトがCPU80186以降で使用できる命令を使用して最適化したものである。原告ソフトは104行及び108行で、CPU8086では使用できない数値や、メモリーの値を直接スタックに待避させて、処理を最適化しただけで、命令、処理は全く同じである。

(三)  「MOVEP」前記のようなルーチンであるが、他の将棋ソフトでも同様の機能の関数は存在すると考えられる。

しかし、

(1) 「MOVEP」自体のコーディング(関数のどの部分をサブルーチン化するのか、また、処理の順番、ローカル、グローバル変数の使い方等のプログラムの骨組など)

(2) 「MOVEP」から呼び出される関数の数や種類、関数に与えるパラメータ

などが、「MOVEP」と全く同じ処理群になることはあり得ない。

書籍等で将棋のプログラムの作り方も紹介されているが、もちろん「MOVEP」のソースプログラムがそのまま掲載されているわけではない。また、書籍に将棋のアルゴリズムの説明として紹介されているプログラムは、非常に簡略化されていて、指し手を実行するのみに止まっている。

(四)  被告ソフトの思考部分では、非常に複雑は構造体を多数使用している。

「MOVEP」の中でも[play p][koma t]、[play p]構造体から[ban t][shurui t]と、構造体同士でも複雑に関与し合っている。

この構造体はソースプログラムと極めて密接な関係にあり、C言語をコンパイルしたときにマシン語プログラムに大きな影響を与えることになる。

したがって、原告ソフトと被告ソフトの逆アセンブルリストの比較により、原告ソフトは構造体ヘアクセスしている部分も被告ソフトと同一である以上、原告ソフトでも被告ソフトと同じ構造体を使用していることは明らかである。

例えば、51行のMOV BX、ES:[SI+04]という命令を例にとると、この中で+04のように+XXで表現されている部分が被告ソフトのプログラムで構造体の中をアクセスしている部分である。

ところが、同一行の原告ソフトと被告ソフトを見比べてみると、プラスの後の数値が同一なのが分かる。この例以外でも、「MOVEP」の中で被告ソフトが構造体をアクセスしている部分は総て数値が同一なので、少なくともplay t、shurui t構造体は同一もしくはほとんど同じ物であるといえる。

また、構造体はプログラムが操作しやすいようにしたものであるから、当然プログラマーの個性や経験により違いが如実に反映する物であり、被告ソフトで使用しているような複雑な構造体が一致することはありえない。もちろん、被告ソフトの構造体は書籍に紹介されている構造体とは全く違う物なので、たとえ同じ書籍を参考としてプログラムを組んだとしても、被告ソフトと同じ構造体になることは余りに不自然である。

(五)  「MOVEP」の中から呼び出されるユーザー定義関数が同一ということは、当然「MOVEP」を呼び出している関数も同じである可能性が高いことを意味する。

「MOVEP」から呼び出される関数の「listup long」を例にとってみると、この関数とこれに相当する原告ソフトのルーチンを逆アセンブルリストを作成して調べてみると、後記のとおり、多少プログラムの順番を変えたり(処理スピードの向上のためと思われる)、必要ない行の削除を行い処理速度を向上させただけのことで、プログラムとしては被告ソフトのプログラムを複製したものであることが分かる。

(六)  以上によれば、原告ソフトの「com-itte」に関するソースプログラムは、「MOVEP」に関する被告ソフトのソースプログラムとほぼ完全に一致し((二)の(1)ないし(5))、一部異なる部分((二)の(6))も、被告ソフトのソースプログラムをオプティマイズしたためであることが明らかである。

したがって、被告ソフトの「MOVEP」の部分に相当する原告ソフトの「com-itte」のソースプログラムは、被告ソフトのソースプログラムに依存しており、被告ソフトのソースプログラムを複製したものであることは明らかである。

3 関数「listup long」について

(一)  被告ソフトのマシン語プログラムのうち関数「listup long」とこれに相当する原告ソフトのルーチンを、逆アセンブルリストを作成して対比すると別紙2のとおり(「聖天Ⅱ」が原告ソフト、「極」が被告ソフトである。)となる。

(二)  右の対比の結果によると、原告ソフトは処理速度向上のため被告ソフトのプログラムの順番を多少変えたり、必要のない行の削除を行い、処理速度を向上させただけのものであることが明らかである。

このようなオプティマイズは、Cコンパイラー自体がある程度行うのであるが、まだ無駄な部分は発生する。被告ソフトは、Cコンパイラーで生成されたコードをそのまま使用しているため、無駄な部分が多少発生したが、この無駄な部分の削除は、ある程度実力を持ったプログラマーなら誰でも同じような変更になるのであって、オプティマイズの作業自体に創作的な部分はない。

したがって、「MOVEP」から呼び出される関数「listup long」も、処理速度の向上を行っただけで、違法に複製されたものである。

第三  判断

一  争点1について

1  (創作性について)

(一) 証拠(甲6、10、証人小林正浩、原告代表者)及び弁論の全趣旨によれば、前記四(被告の主張)、1及び2(二)の事実並びに次ぎの事実を認めることができる。

(1) プログラムの制作において、C言語を使用する場合、言語メーカーが提供する関数のみではプログラムの構築が困難なため、ユーザーが任意の関数を定義して使用する場合が大多数であり、これがユーザー定義関数といわれるもので、それは、C言語のプログラムないしアセンブラのプログラム(ソースプログラム)である。そして、「MOVEP」はその一つのユーザー定義関数であるが、「MOVEP」の中で呼び出されて使用されるユーザー定義関数も、すべて原告側で任意に定義し、創作したプログラムである。

(2) 「MOVEP」は、先読みの探索のため、指し手構造体(Play-t)に格納された利きなどの情報を基に、指し手を実行する思考ルーチンであるが、単に駒を動かしているだけでなく、呼び出されるルーチンによって原告ソフト特有の将棋データの更新や指し手の評価を行うルーチンである。このような機能のルーチンは、探索による思考を行うプログラムには必ず備わっているものではある。そして、その思考プログラムは、コンピュータに合った戦法や定跡を使うことや、最も強いソフトの思考プログラムを参考にしてプログラムされるのが通常であることから、各将棋プログラム間で一部類似点が生ずることがあることは否めないが、駒、盤、指し手構造体など、プログラマーの個性や経験の違いが如実に反映される、各将棋プログラムに特有のデータ構造にアクセスするので、各将棋プログラムごとに異なるのが普通であり、その表現(指令の組み合わせ)がほとんど一致するということは通常はありえない。

(二) ところで、著作権法により保護される著作物は、思想等を「創作的」に表現したものでなければならない。したがって、プログラム(著作権法2条1項10号の2)について著作権の侵害が成立するためには、少なくとも、侵害されたとされるプログラムの表現(指令の組み合わせ)に創作性があり、かつ、侵害したとされるプログラムの表現(指令の組み合わせ)が侵害されたとされるプログラムの創作性のある部分と類似していることが必要である。

そして、もともとプログラムには、その他の著作物と異なり、技術的性格が強く、表現記号も限定されるものであることから、コンピュータを機能させてより効果的に一の結果を得ることを企図すれば、表現(指令の組み合わせ)が必然的に類似することを免れない部分が少なくないという特徴があるが、特に将棋のような完全情報ゲームのプログラムの場合にはそれが強いといえるから、その創作性の有無の判断についてはこの点に留意する必要がある。

なお、プログラムにおける解法(アルゴリズム)自体は、著作物としての保護を受けない部分であるから(著作権法10条3項)、プログラムの創作性とは無関係である。

(三) これを本件についてみると、前記(一)認定の事実によれば、被告ソフトのプログラムである「MOVEP」は、他のルーチンとの構造的関連のもとに、特有の構造にまとめられたデータを操作し、指し手を先読みして実行するルーチンであり、その表現方法は必ずしも将棋プログラムに必然的なものではないと認められるから、前記将棋プログラムの特徴を考慮しても、創作性を有するものと認められる。

2  (類似性について)

(一) 証拠(甲6、10、12、14、証人小林正浩、原告代表者)及び弁論の全趣旨によれば、次の事実が認められる。

(1) 「MOVEP」のソースプログラムと、原告ソフトの同じ機能を有する「com-itte」のソースプログラムとを比較すると、前記認定のとおり別表1のとおりとなり、両者はほとんど同一であり、わずかに異なる部分も、通常の実力をもったプログラマーであれば容易に想到し、改変できる程度のもので、単なるオプティマイズしたに過ぎないものである。

(2) 原告ソフトの制作担当者は、将棋ソフトでは被告ソフトが一番強いという評判であったことから、被告ソフトを逆アセンブルしてそのソースプログラムに接し、これを解析して原告ソフトを制作した。

(二) 上記認定の原告ソフトの制作経過及び被告ソフトの「MOVEP」のソースプログラムとこれに相当する原告ソフトの「com-itte」のソースプログラムとの対比結果に照らせば、原告ソフトの「com-itte」は、被告ソフトの「MOVEP」を基に制作された、これと類似のものと認められる。

原告は、原告ソフトの「com-itte」のソースプログラムが被告ソフトの「MOVEP」のソースプログラムと異なる部分は、「MOVEP」のソースプログラムを単にオプティマイズしたものではなく、それ自体独創性のあるものであり、そのことは、異なる部分を単にオプティマイズしただけでは起こり得ない思考時間の短縮が原告ソフトにあることにも示されている旨主張する。

たしかに、証拠(甲6、10、証人小林正浩)及び弁論の全趣旨によれば、原告ソフトは被告ソフトに比べて思考時間が短いところがあることが認められる。

しかしながら、思考時間の短縮は、「MOVEP」について前記認定の程度のオプティマイズによっても生ずることは明らかであり、それが前記認定のような単なるオプティマイズによるものではなく、原告ソフト独自の創作性に基づくものであることについては、これを認めるにべき証拠はない(どのような原告ソフト独自のプログラムに基づいて思考時間の短縮が生じるのか、原告の主張も、証拠上も明らかでない)。

3  以上によれば、原告ソフトは、被告ソフトの一部のプログラム「MOVEP」と類似性のあるプログラムを含むものであり、そのプログラムは、その機能に照らし、ソフト全体の中のステップ構成割合にかかわらず、被告及び原告各ソフトの重要な部分を構成するものと認められ、したがって、原告ソフト(その販売)は、被告著作権を侵害するものというべきである。

四  結語

よって、原告の各請求は、その余の点につき判断するまでもなく、いずれも理由がないからこれを棄却し、主文のとおり判決する。

(裁判長裁判官 竹中省吾 裁判官小林秀和、同中島真一郎は、転補のため署名捺印できない。 裁判長裁判官 竹中省吾)

別紙

物件目録

以下の内容のマシン語プログラム

1 名称 将棋聖天Ⅱ

2 言語 インテル8086用マシン語

3 用途 NEC PC9801用対戦将棋ソフト

4 動作機種 NEC PC9801シリーズ

5 企画開発 原告

6 発売開始 平成6年2月25日

以上

別紙

著作権目録

一 以下の内容のソースコードプログラム

1 言語 C言語

2 創作年月日 平成4年4月13日

3 用途 NEC PC9801用対戦将棋ソフト

4 開発者 金沢伸一郎

二 以下の内容のマシン語プログラム

1 名称 極

2 言語 インテル8086用マシン語

3 創作年月日 平成4年4月13日

4 用途 NEC PC9801用対戦ソフト

5 動作機種 NEC PC9801シリーズ

6 開発者 金沢伸一郎

7 発売開始 平成4年4月23日

以上

別表1プログラム対比表

聖天 極 極のプログラムの解説及び対比

1.PUSH BP PUSH BP スタックにレジスタBPを待避(このステップは同一である)

2.MOV BP,SP MOV BP,SP レジスタBPにレジスタSPを代入(このステップは同一である)

3.SUB SP,+24 SUB SP,+24 レジスタSPから24H引く(このステップは同一である)これによって、ローカル変数(一時的な変数)が12Hワード(36バイト)使用可能になるテータ構造体koma_tの構造をした*lbuf1[9],*1buf2[9]のローカル変数を確保している普通ポインターは1つに1ワード使うので、9個のポインターで9変数×2セット×2バイト=36バイトとなります

4.PUSH DI PUSH DI スタックにレジスタDIを待避(このステップは同一である)

5.PUSH SI PUSH SI スタックにレジスタSIを待避(このステップは同一である)

6.LES SI,[BP+06] LES SI,[BP+06] レジスタSIに与えられたパラメータ(play_p p)の先頭をセットする(このステップは同一である)これによりレジスタSI=play_p p(以下変数p)になります

7.MOV AX,[B8A8] MOV AX,[8058] レジスタAXに先手の最大予想駒損置のアドレス8058Hの内容を読み込む(聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

8.MOV ES:[SI+13],AX MOV ES:[SI+13],AX 変数pに含まれる変数maxavalの先手用アドレス[SI+13]の位置にレジスタAX(後手の最大予想駒損値)の内容を書き込む(このステップは同一である)

9.MOV AX,[B8AA] MOV AX,[805A] レジスタAXに後手の最大予想駒損置のアドレス805AHの内容を読み込む(聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

10.MOV ES:[SI+15],AX MOV ES:[SI+15],AX 変数pに含まれる変数maxavalの後手用アドレス[SI+15]の位置にレジスタAX(後手の最大予想駒損値)の内容を書き込む(このステップは同一である)

11.CMP Word Ptr ES:[SI],+00 CMP Word Ptr ES:[SI],+00 変数pが何もしない仮想な手かチェックする(このステップは同一である)

12.JNZ 0022 JNZ MOVEP+22(0024) もし仮想な手でなければ処理を続行するので14行ヘジャンプする(聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

13.JMP 013D JMP 0152 この手は仮想手と判断したので処理の終了(111行)ヘジャンプする(聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

14.MOV AX,ES:[SI] MOV AX,ES:[SI] レジスタAXに変数pに含まれる変数fromのアドレス[SI]の内容を読み込む(このステップは同一である)

15.MOV [BB64],AX MOV [86B2],AX 現在の仮想スタックが指すアドレス86B2HにレジスタAX(変数from)の内容を書き込む(聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

16.MOV AX,ES:[SI+02] MOV AX,ES:[SI+02] レジスタAXに変数pに含まれる変数toのアドレス[SI+02]の内容を読み込む(このステップは同一である)

17.MOV [BB66],AX MOV [86B4],AX 現在の仮想スタックが指すアドレス86B4HにレジスタAX(変数to)の内容を書き込む(聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

18.MOV Word Ptr [BEF4],BB68 MOV Word Ptr [8A58],86B6 仮想スタックの位置を指すアドレス8A58に現在の仮想スタックのアドレス86B6Hを書き込む(聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

19.PUSH ES:[SI+04] PUSH ES:[SI+04] 変数pに含まれろ変数movkのアドレス[SI+04]の内容をサブルーチンsub_infoをコールするときに使うパラメータとしスタックに記憶する(このステップは同一である)

20.MOV DI,ES MOV DI,ES レジスタESがサブルーチンで破壊される可能性が有るためレジスタDIに待避(コビー)する(このステップは同一である)

21.CALL 4B82:11F1 CALL ADDINFO TEXT:SUB INFO サブルーチンsub_infoをコールする(極の方はコールするサブルーチンにシンボル(名前)が付いているが、聖天Ⅱは極と同等のサブルーチンをコールしている)

22.MOV ES,DI MOV ES,DI レジスタESが破壊されたので待避しておいたレジスタDIからコピーする(このステップは同一である)

23.MOV BX,ES:[SI+02] MOV BX,ES:[SI+02] レジスタBXに変数pに含まれる変数toのアドレス[SI+02]の内容を読み込む(このステップは同一である)

24.MOV AX,[BX] MOV AX,[BX] レジスタAXに変数toに含まれる変数masuのアドレス[BX]の内容を読み込む(このステップは同一である)

25.MOV ES:[SI+08],AX MOV ES:[SI+08],AX 変数pに含まれる変数capkのアドレス[SI+08]の位置にレジスタAX(変数masu)の内容を書き込む(このステップは同一である)

26.CMP AX,B8D0 CMP AX,13D2 レジスタAXとM_SPACE(盤面上が空き)として登録されているアドレス13D2Hと比べる(M_SPACEはプログラムが起動してから位置を決定するためプログラムの位置によって変化する。聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

27.JZ 0059 JZ MOVEP+57(0059) もし、一致したのなら(移動先に何も駒が無ければ)31行ヘジャンプする(聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

28.PUSH AX PUSH AX 変数pに含まれる変数capkの内容が読み込まれているレジスタAX

をサブルーチンsub_infoをコールする時に使うパラメータとしてスタックに記憶する(このステップは同一である)

29.CALL 4B82:11F1 CALL ADDINFO TEXT:SUB INFO サブルーチンsub_infoをコールする(極の方はコールするサブルーチンにシンボル(名前)が付いているが、聖天Ⅱは極と同等のサブルーチンをコールしている)

30.MOV ES,DI MOV ES,DI レジスタESが破壊されたので待避しておいたレジスタDIからコピーする(このステップは同一である)

31.PUSH ES:[SI] PUSH ES:[SI] 変数pに含まれる変数fromのアドレス[SI]の内容をサブルーチンlistup_longをコールするときに使うパラメータとしてスタックに記憶する(このステップの意味は同一である)

32.MOV BX,ES:[SI+02] MOV BX,ES:[SI+02] レジスタBXに変数pに含まれる変数toのアドレス[SI+02]の内容を読み込む(このステップは同一である)

33.PUSH [BX] PUSH [BX] 変数toに含まれる変数masuのアドレス[BX]の内容をサブルーチンlistup_longをコールするときに使うパラメータとしてスタックに記憶する(このステップは同一である)

34.LEA AX,[BP-12] LEA AX,[BP-12] レジスタAXに関数movepの最初に確保したローカル変数lbuf1のアドレス([BP-12])を読み込む

35.PUSH AX PUSH AX ローカル変数lbuf1位置が読み込まれているレジスタAXをサブルーチンlistup_longをコールするときのパラメータとしてスタックに記憶する(このステップは同一である)

36.MOV DI,ES レジスタESがサブルーチンで破壊される可能性が有るためレジスタDIに待避(コピー)する(22行で既にレジスタESにレジスタDIの値がコピーされ、それ以降DIは破壊されていないためもう1度レジスタDIにコピーし直す必要はない。そのため聖天Ⅱの方では削除して有る)

37.CALL 0577 CALL 088E サブルーチンlistup_longをコールする(聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

38.MOV ES,DI MOV ES,DI レジスタESが破壊されたので待避しておいたレジスタDIからコピーする(このステップは同一である)

39.PUSH ES:[SI+02] PUSH ES:[SI+02] 変数pに含まれる変数toのアドレス[SI+02]の内容をサブルーチンlistup_longをコールするときに使うパラメータとしてスタックに記憶する(このステップは同一である)

40.PUSH ES:[SI+04] PUSH ES:[SI+04] 変数pに含まれる変数movkのアドレス[SI+04]の内容をサブルーチlistup_longをコールするときに使うパラメータとしてスタックに記憶する(このステップは同一である)

41.LEA AX,[BP-24] LEA AX,[BP-24] レジスタAXに関数movepの最初に確保したローカル変数lbuf2のアドレスを読み込む(このステップは同一である)

42.PUSH AX PUSH AX ローカル変数lbuf2の位置が読み込まれているレジスタAXをサブルーチンlistup_longをコールするときのパラメータとして

スタックに記憶する(このステップは同一である)

43.CALL 0577 CALL 088E サブルーチンlistup_longをコールする(聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

44.LEA AX,[BP-12] LEA AX,[BP-12] レジスタAXにローカル変数lbuf1のアドレス([BP-12])を読み込む(このステップは同一である)

45.PUSH AX PUSH AX ローカル変数lbuf1の位置が読み込まれているレジスタAXをサブルーチンsub_infolをコールするときのパラメータとしてスタックに記憶する(このステップは同一である)

46.CALL 4B82:0001 CALL ADDINFO TEXT:SUB INFOL サブルーチンsub_infolをコールする(極の方はコールするサブルーチンにシンボル(名前)が付いているが、聖天Ⅱは極と同等のサブルーチンをコールしている)

47.LEA AX,[BP-24] LEA AX,[BP-24] レジスタAXにローカル変数lbuf2のアドレス([BP-24])を読み込む(このステップは同一である)

48.PUSH AX PUSH AX ローカル変数lbuf2の位置が読み込まれているレジスタAXをサブルーチンsub_infolをコールするときのパラメータとしてスタックに記憶する(このステップは同一である)

49.CALL 4B82:0001 CALL ADDINFO TEXT:SUB INFOL サブルーチンsub_infolをコールする(極の方はコールするサブルーチンにシンボル(名前)が付いているが、聖天Ⅱは極と同等のサブルーチンをコールしている)

50.MOV ES,DI MOV ES,DI レジスタESが破壊されたので待避しておいたレジスタDIからコピーする(このステップは同一である)

51.MOV BX,ES:[SI+04] MOV BX,ES:[SI+04] レジスタBXに変数pに含まれる変数movkのアドレス[SI+04]の内容を読み込む(このステップは同一である)

52.MOV AX,[BX+08] MOV AX,[BX+08] レジスタAXに変数movkに含まれる変数shuのアドレス[BX+08]の内容を読み込む(このステップは同一である)

53.MOV ES:[SI+06],AX MOV ES:[SI+06],AX 変数pに含まれる変数movsのアドレス[SI+06]の位置にレジスタAX(shu)の内容を書き込む(このステップは同一である)

54.CMP Word Ptr ES:[SI],4B84 CMP Word Ptr ES:[SI],85E6 変数pに含まれる変数fromと持ち駒の位置を示すPOS_MOCHIのアドレス85E6Hを比較する(POS_MOCHIはプログラムが起動してから決定するためプログラムの位置によって変化する。聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

55.JZ 00A7 JNZ MOVEP+A8(00AA) もし一致しなければ59行ヘジャンプする(聖天Ⅱの場合、一致したら62行ヘジャンプする)

56.MOV ES,[BP+08] レジスタES(セグメントレジスタ)に変数pの先頭のアドレスを読み直す(この行はCコンパイラーが今までの間にレジスタESが破壊されたと判断し再度与えられたパラメータの先頭アドレスの読み直しを行っている。実際はレジスタESは破壊されて

いないので読み直しは必要ない。そこで聖天Ⅱでは削除されている)

57.JMP MOVEP+B2 (00B4) 62行ヘジャンプする(54行で一致した場合、聖天Ⅱの場合は56行を削除してあるので、直ちに62行ヘジャンプしているが、極では56行の後62行ヘジャンプしている)

58.NOP 全く何もしない行、プログラム的には何もしない。無くても全く支障のない行(聖天Ⅱでは削除されていろ)

59.MOV ES,[BP+08] レジスタES(セグメントレジスタ)に変数pの先頭のアドレスを読み直す(この行はCコンパイラーが今までの間にレジスタESが破壊されたと判断し再度与えられたパラメータの先頭アドレスの読み直しを行っている。実際はレジスタESは破壊されていないので読み直しは必要ない。そこで聖天Ⅱでは削除されている)以上、55行から59行までをまとめると、54行の判定結果に関わらず極では不必要なレジスタESの読み直しを行っている。これはCコンパイラによってコンパイルするとどうしても発生してしまう無駄な処理です。一般的にこれを修正するには1度出力しソースコードをもう1度手直しを加えます。聖天Ⅱは、極のソースコードに手を加え、最適化したものです。

60.MOV BX,ES:[SI] MOV BX,ES:[SI] レジスタBXに変数pに含まれる変数fromのアドレス[SI]の内容を読み込む(このステップは同一である)

61.MOV Word Ptr [BX],B8D0 MOV Word Ptr [BX],13D2 変数fromに含まれる変数masuのアドレス[BX]の位置にM_SPACE(盤面が空きと登録されている)のアドレス13D2Hを書き込む(M_SPACEはプログラムが起動してから位置を決定するためプログラムの位置によって変化する。聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

62.CMP Word Ptr ES:[SI+08],B8D0 CMP Word Ptr ES:[SI+08],13D2 変数pに含まれる変数capkのアドレス[SI+08]とM_SPACE(盤面が空きと登録されている)のアドレス13D2Hを比較する(M_SPACEはプログラムが起動してから位置を決定するためプログラムの位置によって変化する。聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

63.JZ 00DC JZ MOVEP+E7 (00E9) もし、比較結果が一致したら77行ヘジャンプする(聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

64.MOV BX,ES:[SI+08] MOV BX,ES:[SI+08] レジスタBXに変数pに含まれる変数capkのアドレス[SI+08]の内容を読み込む(このステップは同一である)

65.MOV Word Ptr [BX+06],4B84 MOV Word Ptr [BX+06],85E6 変数capkに含まれる変数posのアドレス[BX+06]の位置にPOS_MOCHI(持ち駒の位置が登録されている)のアドレス85E6Hを書き込む(POS_MOCHIはプログラムが起動してから決定

するためプログラムの位置によって変化する。聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

66.MOV DI,ES:[SI+04] MOV DI,ES:[SI+04] レジスタDIに変数pに含まれる変数movkのアドレス[SI+04]の内容を読み込む(このステップは同一である)

67.MOV AL,[DI+01] MOV AL,[DI+01] レジスタALに変数movkに含まれる変数sideのアドレス[DI+01]の内容を読み込む(このステップは同一である)

68.MOV [BX+01],AL MOV [BX+01],AL 変数capkに含まれる変数sideのアドレス[BX+01]の位置にレジスタAL(変数side)の内容を書き込む(このステップは同一である)

69.MOV BX,[BX+08] MOV BX,[BX+08] レジスタBXに変数capkに含まれろ変数shuのアドレス[BX+08]の内容を読み込む(このステップは同一である)

70.MOV ES:[SI+OA],BX MOV ES:[SI+OA],BX 変数pに含まれる変数capsのアドレス[SI+OA]の位置にレジスタBX(変数shu)の内容を書き込む(このステップは同一である)

71.CMP Byte Ptr[BX+01],00 CMP Byte Ptr[Bx+01], setenvp 変数shuに含まれる変数nflagが0か確認する(__setenvp__はCコンパイラーで0が定義されているので、聖天Ⅱと同じ意味である)

72.JZ 00DC JZ MOVEP+E7(00E9) 0だったので77行ヘジャンプする(聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

73.MOV BX,ES:[SI+08] MOV BX,ES:[SI+08] レジスクBX変数pに含まれる変数capkのアドレス[SI+08]の内容を読み込む(このステップは同一である)

74.MOV DI,[BX+08] MOV DI,[BX+08] レジスタDIに変数capkに含まれる変数shuのアドレス[BX+08]の内容を読み込む(このステップは同一である)

75.MOV AX,[DI+04] MOV AX,[DI+04] レジスタAXに変数shuに含まれる変数urapのアドレス[DI+04]の内容を読み込む(このステップは同一である)

76.MOV [BX+08],AX MOV [BX+08],AX 変数capkに含まれる変数shuのアドレス[BX+08]の位置にレジスクA(変数urap)の内容を書き込む(このステップは同一である)

77.MOV AX,ES:[SI+04] MOV AX,ES:[SI+04] レジスタAXに変数pに含まれる変数Movkのアドレス[SI+04]内容を読み込む(このステップは同一である)

78.MOV BX,ES:[SI+02] MOV BX,ES:[SI+02] レジスタBXに変数pに含まれる変数toのアドレス[SI+02]の内容を読み込む(このステップは同一である)

79.MOV [BX],AX MOV [BX],AX 変数toに含まれる変数masuのアドレス[BX]の位置にレジスタAX(変数movk)の内容を書き込む(このステップは同一である)

80.MOV DI,AX MOV DI,AX レジスタAXはオフセットを加えたメモリアクセスが出来ないためレジスタDIにコピーする(このステップは同一である)

81.MOV [DI+06],BX MOV [DI+06],BX 変数movkに含まれる変数posのアドレス[DI+06]の位置にレジスタBX(変数to)の内容を書き込む(このステップは同一である)

82.CMP Byte Ptr Es:[SI+0C].00 CMP Byte Ptr ES:[SI+0C], setenvp 変数pに含まれる変数nariが0か確認する(__setenvp__はCコンパイラーで0が定義されているので、聖天

Ⅱと同じ意味である)

83.JZ 00FF JZ 010C 0だったので88行ヘジャンプする(聖天Ⅱは89行ヘジャンプしている。これは88行を削除してあるためであり、意味は同じである)

84.MOV BX,ES:[SI+04] MOV BX,ES:[SI+04] レジスタBXに変数pに含まれる変数movkのアドレス[SI+04]の内容を読み込む(このステップは同一である)

85.MOV DI,[BX+08] MOV DI,[BX+08] レジスタDIに変数movkに含まれる変数shuのアドレス[BX+08]の内容を読み込む(このステップは同一である)

86.MOV AX,[DI+04] M0V AX,[DI+04] レジスタAXに変数shuに含まれる変数urapのアドレス[DI+04]の内容を読み込む(このステップは同一である)

87.MOV [BX+08],AX MOV [BX+08],AX 変数movkに含まれる変数shuのアドレス[BX+08]の位置にレジスタAx(変数urap)の内容を書き込む(このステップは同一である)

88.MOV ES,[BP+08] レジスタES(セグメントレジスタ)に変数pの先頭のアドレスを読み直す(この行はCコンパイラーが今までの間にレジスタESが破壊されたと判断し再度与えられたパラメータの先頭アドレスの読み直しを行っている。実際はレジスタESは破壊されていないので読み直しは必要ない。そこで聖天Ⅱでは削除されている)

89.PUSH ES:[SI+04] PUSH ES:[SI+04] 変数pに含まれる変数movkのアドレス[SI+04]の内容をサブルーチンadd_infoをコールするときに使うパラメータとしスタックに記憶する(このステップは同一である)

90.M0V DI,ES MOV DI,ES レジスタESがサブルーチンで破壊される可能性が有るためレジスタDIに待避(コピー)する(このステップは同一である)

91.CALL 4B82:00AF CALL ADDINFO TEXT:ADD INFO サブルーチンadd_infoをコール(極の方はコールするサブルーチンにシンボル(名前)が付いているが、聖天Ⅱは極と同等のサブルーチンをコールしている)

92.MOV ES,DI MOV ES,DI レジスクESが破壊されたので待避しておいたレジスクDIからコピーする(このステップは同一である)

93.CMP Word Ptr ES:[SI+08],B8D0 CMP Word Ptr ES:[SI+08],13D2 変数pに含まれる変数capkのアドレス[SI+08]とM_SPACE(盤面が空きと登録されている)のアドレス13D2Hを比較する(M_SPACEはブログラムが起動してから位置を決定するためブログラムの位置によって変化する。聖天Ⅱのアドレスが違うのはブログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

94.JZ 011D JZ 0130 一致したのなら98行ヘジャンプする

95.MOV ES,[BP+08] レジスタES(セグメントレジスタ)に変数pの先頭のアドレスを読み直す(この行はCコンパイラーが今までの間にレジスタESが破壊されたと判断し再度与えられたパラメータの先頭アドレスの読み直しを行っている。実際はレジスタESは破壊されて

いないので読み直しは必要ない。そこで聖天Ⅱでは削除されている

96.PUSH ES:[SI+08] PUSH ES:[SI+08] 変数pに含まれる変数capkのアドレス[SI+08]の内容をサブルーチンadd_infoをコールするときに使うパラメータとしスタックに記憶する(このステップは同一である)

97.CALL 4B82:00AF CALL ADDINFO TEXT:ADD INFO サブルーチンadd_infoをコールする(極の方はコールするサブルーチンにシンボル(名前)が付いているが、聖天Ⅱは極と同等のサブルーチンをコールしている)

98.LEA AX,[BP-12] LEA AX,[BP-12] レジスタAXに関数movepの最初に確保したローカル変数lbuf1([BP-12])のアドレスを読み込む(このステップは同一である)

99.PUSH AX PUSH AX ローカル変数lbuf1の位置が読み込まれているレジスタAXをサブルーチンlistup_longをコールするときのパラメータとしてスタックに記憶する(このステップは同一である)

100.CALL 4B82:008F CALL ADDINFO TEXT:ADD INFOL サブルーチンadd_infolをコールする(極の方はコールするサブルーチンにシンボル(名前)が付いているが、聖天Ⅱは極と同等のサブルーチンをコールしている)。

101.LEA AX,[BP-24] LEA AX,[BP-24] レジスタAXに関数movepの最初に確保したローカル変数lbuf2([BP-24])のアドレスを読み込む(このステップは同一である)

102.PUSH AX PUSH AX ローカル変数lbuf2の位置が読み込まれているレジスタAXをサブルーチンlistup_longをコールするときのパラメータとしてスタックに記憶する(このステップは同一である)

103.CALL 4B82:008F CALL ADDINFO TEXT:ADD INFOL サブルーチンadd_infolをコールする(極の方はコールするサブルーチンにシンボル(名前)が付いているが、聖天Ⅱは極と同等のサブルーチンをコールしている)

104.PUSH [BP+08] MOV AX,[BP+08] レジスタAXに変数pの先頭のアドレスの上位ワード([BP+08])を読み込む

105.PUSH AX 変数pの先頭アドレスの上位ワードが読み込まれているレジスタAXをサブルーチンevalpをコールするときのパラメータとしてスタックに記憶する(聖天Ⅱの場合上位CPU(80186以上)に許された命令を使い、104行で一度に変数Pの先頭アドレスの上位ワードをパラメータとしてスタックに記憶している。従って極の104、105行と聖天Ⅱの104行は同じ意味である。)

106.PUSH SI PUSH SI 変数pの先頭アドレスの下位ワードが読み込まれているレジスタSIをサブルーチンevalpをコールするときのパラメータとしてスタックに記憶する(このステップは同一である)

107.MOV AL,01 レジスタALに1を代入している

108.PUSH 01 PUSH AX 1が代入されているレジスタAXをサブルーチンevalpをコールするときのパラメータとしてスタックに記憶する

(聖天Ⅱの場合上位CPU(80186以上)に許された命令を使い、108行で一度に数値1をパラメータとしてスタックに記憶している。従って、極の107、108行と聖天Ⅱの108行は同じ意味である。)

109.CALL 4A22:014A CALL EVALMOVE TEXT:EVALP サブルーチンevlapをコールする(極の方はコールするサブルーチンにシンボル(名前)が付いているが、聖天Ⅱは極と同等のサブルーチンをコールしている)

110.CALL 055A CALL 086C 仮想スタックをクリアするサブルーチンをコールする(聖天Ⅱのアドレスが違うのはプログラムの置かれる位置によって変化するためであり、このステップの意味は同一である)

111.POP SI POP SI スタックから待避したレジスタSIを復帰する(このステップは同一である)

112.POP DI POP DI スタックから待避したレジスタDIを復帰する(このステップは同一である)

113.MOV SP,BP MOV SP,BP レジスタSPにレジスタBPを代入する(このステップは同一である)

114.POP BP POP BP スタックから待避したレジスタBPを復帰する(このステップは同一である)

115.RETF 0004 RETF 0004 1つ前のルーチンに戻る(このステップは同一である)

別表2

listup_long()

聖天Ⅱ 極

01.PUSH BP PUSH BP スタックにレジスタBPを待避する(この行は同一である)

02.MOV BP,SP MOV BP,SP レジスタBPにレジスタSPを代入する(この行は同一である)

03.PUSH DI PUSH DI スタックにレジスタDIを待避する(この行は同一である)

04.PUSH SI PUSH SI スタックにレジスタSIを待避する(この行は同一である)(上記4行はC言語をコンパイルした場合付加される部分)

05.MOV DI,[BP+04] 聖天Ⅱ側はオプティマイズのためレジスタDIにレジスタ[BP+04]の内容を読み込む(これは与えられたパラメータbufのポインターのアドレスで極では18行で読み込みを行っている)

06.MOV BX,[BP+08] MOV CX,[BP+08] レジスタCX(聖天ⅡではレジスタBX)にアドレス[BP+08]の内容を読み込む

07.CMP BX,4884 CMP CX,85E6 レジスタCX(聖天ⅡではレジスタBX)とPOS_MOCHIと同じかをチェックする(アドレス[BP+O8]がPOS_MOCHIと同じであるか判定すると言う意味は同じである)

08.JZ 05C0 JZ 08DA もし、同じでなければ35行に飛ぶ(この行の意味は同一である)

09.MOV BX,CX レジスタCXにレジスタBXを読み込む

10.TEST Word Ptr [BX+6F],1E02 TEST Word Ptr [BX+6F],1E02 アドレス[BX+6F]の内容が長い利きを持った駒か判定する(この行は同一である)

11.JNZ 0597 JNZ 08AD もし長い利きの駒ならば14行に飛ぶ(この行は同一である)

12.TEST Word Ptr [BX+009E],1E02 TEST Word Ptr [BX+009E],1E02 アドレス[BX+9E]の内容が長い利きを持った駒か判定する(この行は同一である)

13.JZ 05C0 JZ 08DA もし長い利きの駒でないのなら35行に飛ぶ(この行は同一である)

14.MOV SI,[38E2] MOV SI,[035A] レジスタSIにアドレス[035A](聖天Ⅱは[38E2])の内容を読み込む(この行に命令のは同一である

15.OR SI,SI OR SI,SI レジスタSIの内容が0であるか判定する(この行は同一である)

16.JZ 05C0 JZ 08DA もし、0ならば35行に飛ぶ(この行は同一である)

17.MOV CX,BX レジスタCXにレジスタBXを読み込むMOV DI,[BP+04] レジスタDIにアドレス[BP+04]の内容を読み込む(聖天Ⅱはオプティマイズの関係上5行で既に行われている)

18.MOV DX,[BP+06] MOV DX,[BP+06] レジスタDXにアドレス[BP+06]の内容を読み込む(この行は同一である)

19.CMP SI,DX CMP SI,DX レジスタSIとレジスタDXの内容が同じか判定する(この行は同一である)

20.JZ 05B9 JZ 08D0 もし、同一なら31行に飛ぶ(この行は同一である)

21.XOR BX,BX レジスタBXを0にする

22.MOV BL,[SI] MCV BL,[SI] レジスタBLにレジスタ[SI]の内容を読み込んでいる(この行は同一である)

23.SUB BH,BH レジスタBLをレジスタBXに拡張するのに必要ない部分を0にする

(アドレス[SI]の8ビットのデータをレジスタBXに16ビットに拡張して読み込む処理は同一である)

24.ADD BX,CX ADD BX,CX レジスタBXにレジスタCXを足す(この行は同一である)

25.TEST Byte Ptr [BX+38],10 TEST Byte Ptr [BX+38],10 アドレス[BX+38]の内容の第4ビットが立っているか調べる(この行は同一である)

26.JZ 05B9 JZ 08D0 もし立っていなければ31行にジャンプする(この行は同一である)

27.INC DI レジスタDIを1進める(レジスタDIに1を足す)

28.INC DI 〃

29.MOV [DI],SI MOV [DI-02],SI [DI-2](聖天Ⅱでは[DI])にレジスタSIを書き込む

30.ADD DI,+02 レジスタDIに2を足している(上4行で行っていることは、レジスタDIの示すアドレスにレジスタSIを書き込んだ後レジスタDIを2足している)(リストアップした内容をレジスタDIに書き込む処理は同一である)

31.MOV SI,[SI+OA] MOV SI,[SI+OA] レジスタSIにレジスタ[SI+OA]の内容を読み込んでいる(この行は同一である)

32.OR SI,SI OR SI,SI レジスタSIの内容が0であるか調べる(この行は同一である)

33.JNZ 05A4 JNZ 08BB もし、0でなければ19行へ飛ぶ

34.MOV [BP+04],DI レジスタDIをワークエリア[BP+04]にDIを記憶する

35.MOV BX,[BP+04] レジスタBXをワークエリア[BP+04]の内容を読み込む

36.MOV Word Ptr [DI],0000 MOV Word Ptr [BX],_setenvp_ レジスタBX(聖天ⅡではレジスタDI)にエンドマークの0を書き込む(上3行はリストアップしたデータにエンドマーク0を書き込んでいる)(レジスタDIのアドレスにエンドマーク0を書き込む処理は同一である)

37.POP SI POP SI スタックからレジスタSIを復帰する(この行は同一である)

38.POP DI POP DI スタックからレジスタDIを復帰する(この行は同一である)

39.MOV SP,BP MOV SP,BP レジスタSPにレジスタBPを代入する(この行は同一である)

40.POP BP POP BP スタックからレジスタBPを復帰する(この行は同一である)

41.RET 0006 RET 0006 1つ上の関数に戻る(この行は同一である)

自由と民主主義を守るため、ウクライナ軍に支援を!
©大判例